﻿
#region Using directives

using System;
using System.Collections.Generic;
using System.Text;

using FamilyTreeProject.Framework.Enums;
using FamilyTreeProject.Framework.Structures;

#endregion

namespace FamilyTreeProject.Framework.Entities
{
    /// <summary>
    /// The Event Class models a Genealogical Event Record.
    /// </summary>
    public class Event : EntityBase, IEvent
    {

        #region Fields

        //TODO Change place strings to objects
        private EventClass eventClass = EventClass.Individual;
        private DateRange date = null;
        private IList<IParticipant> participants;
        private string place = "";
        private string religion = "";
        private EventType type = EventType.Unknown;
        private string typeDetail = "";

        #endregion

        #region Constructors

        /// <summary>
        /// Constructs an empty event
        /// </summary>
        internal Event() : this(-1) { }

        /// <summary>
        /// Constructs an empty event with the specified ID
        /// </summary>
        /// <param name="id">The ID for the new event</param>
        internal Event(int id) : base(id)
        {
            participants = new List<IParticipant>();
        } 

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the date of the event
        /// </summary>
        /// <value></value>
        public DateRange Date
        {
            get { return date; }
            set { date = value; }
        }

        /// <summary>
        /// Gets or sets the EventClass of the event
        /// </summary>
        /// <value></value>
        public EventClass EventClass
        {
            get { return eventClass; }
            set { eventClass = value; }
        }

        /// <summary>
        /// Gets whether the Event is a Family Event
        /// </summary>
        /// <value>true/false</value>
        public bool IsFamilyEvent
        {
            get { return (eventClass == EventClass.Family); }
        }

        /// <summary>
        /// Gets whether the Event is an Individual Event
        /// </summary>
        /// <value>true/false</value>
        public bool IsIndividualEvent
        {
            get { return (eventClass == EventClass.Individual); }
        }

        /// <summary>
        /// Gets the participants collection
        /// </summary>
        public IList<IParticipant> Participants
        {
            get { return participants; }
        }

        /// <summary>
        /// Gets or sets the place of the event
        /// </summary>
        /// <value></value>
        public string Place
        {
            get { return place; }
            set { place = value; }
        }

        /// <summary>
        /// Gets or sets the religion sponsoring the event
        /// </summary>
        /// <value></value>
        public string Religion
        {
            get { return religion; }
            set { religion = value; }
        }

        /// <summary>
        /// Gets or sets the type of the event
        /// </summary>
        /// <value></value>
        public EventType Type
        {
            get { return type; }
            set { type = value; }
        }

        /// <summary>
        /// Gets or sets the Type Detail of the event
        /// </summary>
        /// <value></value>
        public string TypeDetail
        {
            get { return typeDetail; }
            set { typeDetail = value; }
        }


        #endregion

        #region Public Methods

        /// <summary>
        /// Fetch the First Individual of a Given Role
        /// </summary>
        /// <param name="role">The role to fetch</param>
        /// <returns>The returned Individual</returns>
        public IIndividual FindIndividualByRole(string role)
        {
            IIndividual retValue = null;

            foreach (IParticipant par in participants)
            {
                if (par.Role == role)
                {
                    retValue = par.Individual;
                    break;
                }
            }

            return retValue;
        }

        /// <summary>
        /// Fetch all the Individuals of a Given Role
        /// </summary>
        /// <param name="role">The role to fetch</param>
        /// <returns>The returned Individuals</returns>
        public IList<IIndividual> FindIndividualsByRole(string role)
        {
            IList<IIndividual> retValue = new List<IIndividual>();

            foreach (IParticipant par in participants)
            {
                if (par.Role == role)
                {
                    retValue.Add(par.Individual);
                    break;
                }
            }

            return retValue;
        }

        /// <summary>
        /// Get the Role in the Event of the Individual suppplied
        /// </summary>
        /// <param name="ind">The Individual</param>
        /// <returns>The role of the Individual </returns>
        public string GetRole(IIndividual ind)
        {
            string retValue = "<Unknown>";

            foreach (IParticipant par in participants)
            {
                if (par.Individual == ind)
                {
                    retValue = par.Role;
                    break;
                }
            }

            return retValue;
        }

        /// <summary>
        /// Gets the vital type of the event
        /// </summary>
        /// <returns>The vital type as a string</returns>
        public string GetVitalType()
        {
            string retValue = "";

            switch (type)
            {
                case EventType.Baptism:
                case EventType.Birth:
                case EventType.Christening:
                    retValue = "birth";
                    break;
                case EventType.Burial:
                case EventType.Cremation:
                case EventType.Death:
                    retValue = "death";
                    break;
                case EventType.Marriage:
                case EventType.Marriage_Bann:
                case EventType.Marriage_Contract:
                case EventType.Marriage_License:
                    retValue = "marriage";
                    break;
                default:
                    retValue = "";
                    break;
            }

            return retValue;
        }

        #endregion

        #region IComparable Members

        /// <summary>
        /// CompareTo Implementation, compares by using the date of the event
        /// </summary>
        /// <param name="obj">The object to compare</param>
        /// <returns>-1, 0 or +1</returns>
        public int CompareTo(object obj)
        {
            Int32 retValue = 0;

            if (obj is IEvent)
            {
                IEvent temp = (IEvent)obj;

                //Compare dates
                if (date == null && temp.Date == null)
                {
                    retValue = 0;
                }
                else if (date == null)
                {
                    retValue = +1;
                }
                else if (temp.Date == null)
                {
                    retValue = -1;
                }
                else
                    retValue = date.CompareTo(temp.Date);
            }
            else
            {
                throw new ArgumentException("object is not an Event");
            }

            return retValue;
        }

        #endregion

    }
}
